Extending LValuable Subs with Tied Variables

Limbic Region on 2004-06-24T16:47:29

Sort of crossposted from: http://www.perlmonks.org/index.pl?node_id=369354

A new monk at the Monastery wanted to be able to use the following syntax to get/set properties

my $name = $obj->name; $obj->name = "Limbic";

Ok - use an lvaluable sub right. Well the new monk also wanted to be able to pre/post process like C# (which I don't have any knowledge of):

$obj->name = "Limbic"; print $obj->name, "\n"; # "Limbic post processed"

After getting nowhere trying to convince the monk to use the conventional syntax, I decided to give it a shot. I came up with the following in about 20 minutes (I had never used lvaluable subs before and have only used tied variables a few times)

package magic;

sub TIESCALAR { my $class = shift; die "Incorrect number of parameters" if @_ % 2; my $self = bless {}, $class; $self->_Init(@_); return $self; }

sub _Init { my ($self, %opt) = @_; $self->{PRE} = $opt{PRE} || sub { return uc $_[0] }; $self->{POST} = $opt{POST} || sub { my $val = shift; $val =~ s/FOO/BAR/; return $val; }; return; }

sub STORE { my ($self, $value) = @_; $value = $self->{PRE}->( $value ); $value = $self->{POST}->( $value ); $self->{VAL} = $value; }

sub FETCH { return $_[0]->{VAL} }

########################################

package cool;

sub new { my $class = shift; tie my $name, "magic", @_; bless \$name, $class; }

sub name :lvalue { ${$_[0]}; }

########################################

package main;

tie my $string, "magic"; $string = 'My left foot'; print "$string\n";

my $obj = cool->new( 'POST' => sub { return reverse $_[0] } );

$obj->name = "My right foot"; print $obj->name, "\n";

I posted the following questions after the response: Is there a better way of doing this? Is it hard to extend Attribute::Property to do this? If this is the way to do it, how can it be wrapped up in a module like Attribute::Property to make it easier to use?

Since I haven't (as of yet) gotten any feedback at the Monastery I figured I would throw it out here as well.


Wrapping subs

runrig on 2004-06-24T20:37:57

Hook::LexWrap or Hook::WrapSub might be worth taking a look at.

Reply

Juerd on 2004-06-24T22:55:08

http://perlmonks.org/index.pl?node_id=369511